unit uniMenuGL;

interface

uses
  uniMainToolkit,
  ftgl,
  SysUtils,
  gl,
  sdl,
  Math,
  Classes;

const
  NumMssg = 6;

type

  MenuSelection =
    (
    NewGame,
    GameLevel,
    SkillLevel,
    Graphics,
    FullScreen,
    ScreenSize,
    Sound,
    Music,
    MouseSpeed,
    Quit,
    NumSelections
    );

  { MenuGL }

  MenuGL = class(TObject)
  public
    curSel: MenuSelection;

    menutext: array[0..Integer(NumSelections) - 1] of string;

    listChrom: GLuint;
    listBSU: GLuint;

    envTex: GLuint;
    csrTex: GLuint;
    backTex: GLuint;
    elecTex: Gluint;
    updwnTex: GLuint;

    elecOffX: Single;
    elecOffY: Single;
    elecStretch: Single;
    textAngle: Single;
    textCount: Integer;

    txtHeight: Single;
    butHeight: Single;
    butWidth: Single;
    butOffset: Single;

    thickText: Boolean;

    titleTilt: Single;

    mssgAlpha: Single;
    mssgText: string;
    mssgIndex: Integer;
    mssgCount: Integer;
    mssgHelpOverride: Boolean;

    // game: Global;


    constructor Create;
    destructor Destroy; override;

    procedure startMenu;
    procedure keyhit(_key: key);
    procedure mousePress(but: Button; xi, yi: Integer);

    procedure drawGL;

    procedure loadTextures;
    procedure deleteTextures;

    procedure activateItem;
    procedure incItem;
    procedure decItem;

    procedure drawIndicator;
    procedure drawElectric;

    procedure drawTitle;
    procedure drawTitleBack;

    procedure createLists(thick: Boolean);
  end;

var
  c: Double = 0.0;
  mssgHelpText: array[0..NumMssg - 1] of string =
  (
    '  d o   n o t   a l l o w  -a n y-   e n e m i e s   g e t   p a s t   y o u !',
    '  e v e r y   e n e m y   t h a t   g e t s   b y   c o s t s   y o u   a   l i f e !',
    '  a l l o w   p o w e r - u p s   t o   p a s s   b y   f o r   b i g   p o i n t s !',
    '  c r a s h   i n t o   e n e m i e s   t o   d e s t r o y   t h e m !',
    '  r i g h t   c l i c k   t w i c e   t o   s e l f - d e s t r u c t !',
    '  s e l f - d e s t r u c t   t o   p r e s e r v e   y o u r   a m m u n i t i o n !'
    );

  tiltCount: Integer = 600;
  ta0: Single = -60.0;
  ta1: Single = -90.0;

  amt: Single = 0.0;

function skillString(i: Integer): string;

implementation

uses
  PNGLoader,
  uniDefine,
  unitextGeometryChromium,
  unitextGeometryBSU,
  uniHiScore,
  uniAudio,
  uniConfig,
  uniGlobal;

function skillString(i: Integer): string;
begin
  case i of
    2: Result := 'fish in a barrel';
    3: Result := 'whimp';
    4: Result := 'easy';
    5: Result := 'normal';
    6: Result := 'experienced';
    7: Result := 'fun';
    8: Result := 'insane';
    9: Result := 'impossible';
  else
    Result := '-';
  end;
end;


{ MenuGL }

procedure MenuGL.activateItem;
var
  _config: Config;
  game: Global;
begin
  _config := uniConfig.instance;
  game := uniGlobal.getInstance;
  case curSel of
    NewGame:
      begin
        _gameMode := uniGlobal.Game;
        game.newGame;
        toolkit.grabMouse(True);
        _audio.setMusicMode(MusicGame);
      end;
    SkillLevel, GameLevel, Graphics, ScreenSize:
      begin

      end;
    FullScreen:
      begin
        _config.setFullScreen(not _config.fullScreen);
        game.deleteTextures;
        toolkit.setVideoMode;
        game.loadTextures;
      end;
    Sound, Music, MouseSpeed:
      begin

      end;
    Quit: game.game_quit := Integer(True);
    NumSelections:
      begin

      end;
  end;
end;

constructor MenuGL.Create;
begin
  curSel := NewGame;

  elecStretch := 10.0;
  elecOffX := 0.0;
  elecOffY := 0.0;
  textAngle := 0.0;
  txtHeight := 0.5;
  titleTilt := -10.0;

  butHeight := 0.5;
  butWidth := butHeight * 4.0;
  butOffset := 3.05;

  menuText[Integer(NewGame)] := 'n e w    g a m e';
  menuText[Integer(GameLevel)] := 'l e v e l';
  menuText[Integer(SkillLevel)] := 's k i l l';
  menuText[Integer(Graphics)] := 'g f x    d e t a i l';
  menuText[Integer(FullScreen)] := 'f u l l s c r e e n';
  menuText[Integer(ScreenSize)] := 's c r e e n    s i z e';
  menuText[Integer(Sound)] := 's o u n d    f x    v o l u m e';
  menuText[Integer(Music)] := 'm u s i c    v o l u m e';
  menuText[Integer(MouseSpeed)] := 'm o u s e   s p e e d';
  menuText[Integer(Quit)] := 'q u i t';

  loadTextures;
  thickText := true;
  mssgAlpha := 0.0;
  //sprintf(mssgText, ' ');
  mssgText := ' ';
  mssgIndex := 0;
  mssgCount := 0;
  mssgHelpOverride := false;

  startMenu;
end;

procedure MenuGL.createLists(thick: Boolean);
begin
  if not thick then
  begin

  end;
  titleTilt := -10.0;

  glNewList(listChrom, GL_COMPILE);
  textGeometryChromium(thick);
  glEndList;

  glNewList(listBSU, GL_COMPILE);
  textGetometryBSU(thick);
  glEndList;
end;

procedure MenuGL.decItem;
var
  _config: Config;
  _hiScore: HiScore;
  game: Global;
  pos: array[0..2] of Single;
begin
  _config := uniConfig.instance;
  _hiScore := uniHiScore.getInstance;
  game := uniGlobal.getInstance;
  pos[0] := 0.0;
  pos[1] := 0.0;
  pos[1] := 25.0;
  case curSel of
    Quit, NumSelections, NewGame:
      begin

      end;
    SkillLevel:
      begin
        _config.setGameSkillBase(_config.gameSkillBase - 0.1);
        _hiScore.print(_config.intSkill);
        game.newGame;
      end;
    GameLevel:
      begin
        uniGlobal.gameLevel := uniGlobal.gameLevel - 1;
        if uniGlobal.gameLevel < 1 then uniGlobal.gameLevel := 1;
        game.newGame;
      end;
    Graphics:
      begin
        _config.setGfxLevel(_config.gfxLevel - 1);
      end;
    ScreenSize:
      begin
        _config.setScreenSize(_config.screenSize - 1);
        game.deleteTextures;
        toolkit.setVideoMode;
        game.loadTextures;
      end;
    FullScreen:
      begin
        if _config.fullScreen then
        begin
          _config.setFullScreen(false);
          game.deleteTextures;
          toolkit.setVideoMode;
          game.loadTextures;
        end;
      end;
    Sound:
      begin
        _config.setVolSound(_config.volSound - 0.05);
        _audio.setSoundVolume(_config.volSound);
        _audio.playSound(uniAudio.Explosion, pos);
      end;
    Music:
      begin
        _config.setVolMusic(_config.volMusic - 0.05);
        _audio.setMusicVolume(_config.volMusic);
      end;
    MouseSpeed:
      begin
        _config.setMouseSpeed(_config.mouseSpeed - 0.005);
      end;
  end;
end;

procedure MenuGL.deleteTextures;
begin
  glDeleteTextures(1, @elecTex);
  glDeleteTextures(1, @backTex);
  glDeleteTextures(1, @envTex);
  glDeleteTextures(1, @csrTex);
  glDeleteTextures(1, @updwnTex);
  elecTex := 0;
  backTex := 0;
  envTex := 0;
  csrTex := 0;
  updwnTex := 0;
  glDeleteLists(listChrom, 1);
  glDeleteLists(listBSU, 1);
end;

destructor MenuGL.Destroy;
begin
  deleteTextures;
  //inherited;
end;

procedure MenuGL.drawElectric;
var
  es: Single;
  szx, szy: Single;
begin
  es := elecStretch;
  elecOffY := FRAND * 0.7;
  elecOffX := elecOffX + 0.175;
  if elecOffX > es then elecOffX := -5.0;
  szx := 30.0;
  szy := txtHeight;
  glBindTexture(GL_TEXTURE_2D, elecTex);
  glPushMatrix;
  glTranslatef(0.0, txtHeight * 0.5, 0.0);
  glBegin(GL_QUADS);
  glColor4f(1.0, 1.0, 1.0, 1.0);
  glTexCoord2f(elecOffX, elecOffY + 0.3); glVertex3f(-8.0, szy, 0.0);
  glTexCoord2f(elecOffX, elecOffY); glVertex3f(-8.0, -szy, 0.0);
  glColor4f(0.0, 0.0, 0.1, 1.0);
  glTexCoord2f(elecOffX - es, elecOffY); glVertex3f(szx, -szy, 0.0);
  glTexCoord2f(elecOffX - es, elecOffY + 0.3); glVertex3f(szx, szy, 0.0);
  glEnd;
  glPopMatrix;
end;

procedure MenuGL.drawGL;
var
  _config: Config;
  game: Global;
  _hiScore: HiScore;
  i, l, recentHiScore, len, n, ti, interval: Integer;

  szx, szy, _top, _left, _inc, sc, f, r, trans, alpha: Single;
  buf: string;
  nowTime, mostRecent: Int64;
begin
  _config := uniConfig.instance;
  game := uniGlobal.getInstance;
  _hiScore := uniHiScore.getInstance;

  Dec(textCount);
  if textCount < 0 then
  begin
    textCount := 500;
  end;
  if textAngle > 0.0 then
    textAngle := textAngle - 5.0
  else
    textAngle := 0.0;

  //-- Clear buffers
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

  //-- Place camera
  glLoadIdentity;
  glTranslatef(0.0, 0.0, _config.zTrans);

  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  glColor4f(1.0, 1.0, 1.0, 1.0);

  //-- Draw background
  _ground.drawGL;

  //-- Update audio
  _audio.update;

  szx := 9.0;
  szy := 4.5;
  _top := 1.0;
  _left := -8.0;
  _inc := -txtHeight * 2.5;

  //----- Draw credits texture ------------------------------------------
  glPushMatrix;
  // NOTE: corners of back tex is white, alpha 1 and
  // we are in modulate blend...
  glBindTexture(GL_TEXTURE_2D, backTex);
  glTexCoord2f(1.0, 0.0);

  //-- darken
  glBegin(GL_QUADS);
  glColor4f(0.0, 0.0, 0.0, 0.8);
  glVertex3f(szx, szy + 0.25 - 3.0, 10.0);
  glVertex3f(-szx, szy + 0.25 - 3.0, 10.0);
  glColor4f(0.0, 0.0, 0.0, 0.4);
  glVertex3f(-szx, -13.0, 10.0);
  glVertex3f(szx, -13.0, 10.0);
  glEnd;
  glBegin(GL_QUADS);
  glColor4f(0.0, 0.0, 0.0, mssgAlpha);
  glVertex3f(16.0, -10.7, 10.0);
  glVertex3f(-16.0, -10.7, 10.0);
  glColor4f(0.0, 0.0, 0.0, mssgAlpha);
  glVertex3f(-16.0, -11.9, 10.0);
  glVertex3f(16.0, -11.9, 10.0);
  glEnd;
  szx := 12.0;
  szy := txtHeight * 0.5;
  glPushMatrix;
  glTranslatef(_left, _top + (_inc * Integer(curSel)), 10.0);
  glBegin(GL_QUADS);
  glColor4f(0.5, 0.5, 1.0, 1.0);
  glVertex3f(-szx, szy * 3.0, 0.0);
  glVertex3f(-szx, -szy, 0.0);
  glColor4f(0.2, 0.2, 1.0, 0.0);
  glVertex3f(szx, -szy, 0.0);
  glVertex3f(szx, szy * 3.0, 0.0);
  glEnd;
  drawIndicator;

  glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  drawElectric;
  glPopMatrix;
  glColor4f(1.0, 1.0, 1.0, 0.9);

  sc := 0.035;
  for i := 0 to Integer(NumSelections) - 1 do
  begin
    glPushMatrix;
    glTranslatef(_left, _top + (_inc * i), 10.0);
    glRotatef(textAngle, 1.0, 0.0, 0.0);
    glScalef(sc, sc * 0.75, 1.0);
    //game.ftFont.Render(menuText[i]);
    ftglRenderFont(uniGlobal.ftFont, PAnsiChar(menuText[i]));
    glPopMatrix;
  end;

  f := uniGlobal.frame;
  r := cos(f * 0.02);
  glPushMatrix;
  glColor4f(1.0, 1.0, 1.0, 0.6 + 0.2 * r);
  glTranslatef(-18.75, -8.5, 0.0);
  glScalef(sc, sc * 0.75, 1.0);
  //game.ftFont.Render("high scores");
  ftglRenderFont(uniGlobal.ftFont, 'high scores');
  glTranslatef(-100.0, -30.0, 0.0);
  //time_t nowTime = time(NULL);
  nowTime := SDL_GetTicks;
  l := _config.intSkill;
  recentHiScore := -1;
  mostRecent := 0;
  for i := 0 to HI_SCORE_HIST - 1 do
  begin
    if (_hiScore.getDate(l, i) > nowTime - 300) and // highlight score for 5 minutes (300)
    (_hiScore.getDate(l, i) > mostRecent) then
    begin
      recentHiScore := i;
      mostRecent := _hiScore.getDate(l, i);
    end;
  end;
  for i := 0 to HI_SCORE_HIST - 1 do
  begin
    f := f + 30.0;
    r := cos(f * 0.02);
    if i = recentHiScore then
      glColor4f(1.5, 0.5, 0.5, 0.6 + 0.1 * r)
    else
      glColor4f(1.0, 1.0, 1.0, 0.2 + 0.2 * r);
    //sprintf(buf, "%d", (int)hiScore.getScore(config.intSkill, i) );
    buf := IntToStr(Round(_hiScore.getScore(_config.intSkill, i)));
    //len := strlen(buf);
    len := Length(buf);
    //trans := 80.0 + game.ftFont.Advance("high scores") - game.ftFont.Advance(buf);
    trans := 80.0 + ftglGetFontAdvance(uniGlobal.ftFont, 'high scores') - ftglGetFontAdvance(uniGlobal.ftFont, PAnsiChar(buf));
    glTranslatef(trans, 0.0, 0.0);
    //game.ftFont.Render(buf);
    ftglRenderFont(uniGlobal.ftFont, PAnsiChar(buf));
    glTranslatef(-trans, -30.0, 0.0);
  end;
  glPopMatrix;

  //---- credits
  if True then
  begin
    n := 0;
    if c > 75.0 then
    begin
      c := 0.0;
    end;

    c := c + 0.2;
    glPushMatrix;
    if c > 25 then alpha := 0.4 * (75.0 - c) / 50.0
    else alpha := 0.4;
    glColor4f(1.0, 1.0, 1.0, alpha);
    sc := 0.03;
    glTranslatef(14.0, -11.5, 0.0);
    glScalef(sc, sc, 1.0);
    glTranslatef(-c * 1.5, c, 0.0);

    if (c < 3) then n := Round(c)
    else n := 3;
    //game.ftFont.Render("the", n);
    ftglRenderFont(uniGlobal.ftFont, 'the');
    //glTranslatef(c-game.ftFont.Advance("the", n), -38+c, 0.0);
    glTranslatef(c - ftglGetFontAdvance(uniGlobal.ftFont, 'the'), -38 + c, 0.0);
    if (c < 10) then n := Round(c - 3)
    else n := 7;
    //game.ftFont.Render("reptile", n);
    ftglRenderFont(uniGlobal.ftFont, 'reptile');
    //glTranslatef(c-game.ftFont.Advance("reptile", n), -38+c, 0.0);
    glTranslatef(c - ftglGetFontAdvance(uniGlobal.ftFont, 'reptile'), -38 + c, 0.0);
    if (c < 16) then n := Round(c - 10)
    else n := 6;
    //game.ftFont.Render("labour", n);
    ftglRenderFont(uniGlobal.ftFont, 'labour');
    //glTranslatef(c-game.ftFont.Advance("labour", n), -38+c, 0.0);
    glTranslatef(c - ftglGetFontAdvance(uniGlobal.ftFont, 'labour'), -38 + c, 0.0);
    if (c < 23) then n := Round(c - 16)
    else n := 7;
    //game.ftFont.Render("project", n);
    ftglRenderFont(uniGlobal.ftFont, 'project');
    // font height is 23
    glPopMatrix();
  end;

  //-------- draw help message
  if mssgAlpha > 0.0 then
  begin
    if mssgHelpOverride then
      glColor4f(1.3, mssgAlpha, mssgAlpha, mssgAlpha)
    else
      glColor4f(0.5, 0.5, 0.9, (0.2 + mssgAlpha));
    sc := 0.042;
    glTranslatef(-19.5, -14.0, 0.0);
    glScalef(sc, sc * 0.75, 1.0);
    ti := Round(112.0 * mssgAlpha);
    if ti > Length(mssgText) then ti := Length(mssgText);
    //game->ftFont->Render(mssgText, ti);
    ftglRenderFont(uniGlobal.ftFont, PAnsiChar(mssgText));
    mssgAlpha := mssgAlpha - 0.004;
    glColor4f(1.0, 1.0, 1.0, 1.0);
  end;

  glPopMatrix;

  glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  glPushMatrix;
  glTranslatef(0.0, 4.75, 25.0);
  glColor4f(1.0, 1.0, 1.0, 1.0);
  glDepthMask(GL_FALSE); //XXX Hack to make Voodoo3 XF4 work
  drawTitleBack;
  glDepthMask(GL_TRUE); //XXX Hack to make Voodoo3 XF4 work
  drawTitle;
  glPopMatrix;

  if thickText and (uniGlobal.fps < 30) then
  begin
    //fprintf(stderr, "ATTENTION: Using 'thin' text to improve framerate...\n");
    thickText := false;
    createLists(thickText);
  end;
  if not thickText and (uniGlobal.fps > 40) then
  begin
    //fprintf(stderr, "ATTENTION: Reverting to 'thick' text...\n");
    thickText := true;
    createLists(thickText);
  end;
  //---------- Help messages
  if mssgHelpOverride and (mssgAlpha < 0.05) then
  begin
    mssgHelpOverride := false;
    mssgCount := 0;
  end;
  if not mssgHelpOverride then
  begin
    Inc(mssgCount);
    interval := mssgCount mod 500;
    if not Boolean(interval) then
    begin
      //strcpy(mssgText, mssgHelpText[mssgIndex%NumMssg]);
      mssgText := mssgHelpText[mssgIndex mod NumMssg];
      Inc(mssgIndex);
    end;
    if interval < 150 then
    begin
      mssgAlpha := interval / 150.0;
    end;
  end;
end;

procedure MenuGL.drawIndicator;
var
  _config: Config;
  game: Global;

  buf: string;
  szx, szy, level, sc, bx, by, bo: Single;
  tmp: Integer;
begin
  _config := uniConfig.instance;
  game := uniGlobal.getInstance;
  szx := 10.0;
  szy := txtHeight;
  level := 0.0;
  sc := 0.025;

  case curSel of
    GameLevel:
      begin
        level := uniGlobal.gameLevel / 9.0;
        buf := IntToStr(uniGlobal.gameLevel);
      end;
    SkillLevel:
      begin
        level := _config.gameSkillBase;
        tmp := Round((level + 0.05) * 10.0);
        buf := skillString(tmp);
      end;
    Graphics:
      begin
        level := _config.gfxLevel / 2.0;
        case _config.gfxLevel of
          0: buf := 'low';
          1: buf := 'med';
          2: buf := 'high';
        end;
      end;
    ScreenSize:
      begin
        level := _config.screenSize / MAX_SCREEN_SIZE;
        case _config.screenSize of
          0: buf := '512x384';
          1: buf := '640x480';
          2: buf := '800x600';
          3: buf := '1024x768';
          4: buf := '1280x960';
        end;
      end;
    FullScreen:
      begin
        level := Integer(_config.fullScreen);
        if _config.fullScreen then buf := 'true'
        else buf := 'false';
      end;
    Sound:
      begin
        level := _config.volSound;
        buf := IntToStr(round((level + 0.05) * 10.0));
      end;
    Music:
      begin
        level := _config.volMusic;
        buf := IntToStr(round((level + 0.05) * 10.0));
      end;
    MouseSpeed:
      begin
        level := _config.mouseSpeed * 10.0;
        buf := IntToStr(round((level + 0.005) * 100.0));
      end;
  else
    level := -5.0;
  end;


  glPushMatrix;

  glTranslatef(0.0, -txtHeight, 0.0);
  glBegin(GL_QUADS);
  glColor4f(1.0, 1.0, 1.0, 0.3);
  glVertex3f(szx + szy, szy, 0.0);
  glVertex3f(-szx, szy, 0.0);
  glColor4f(1.0, 1.0, 1.0, 0.15);
  glVertex3f(-szx, 0.0, 0.0);
  glVertex3f(szx, 0.0, 0.0);
  glEnd;

  //-- draw level indicator and/or text
  glPushMatrix;

  if level > -1.0 then
  begin

    glBegin(GL_QUADS);
    glColor4f(1.0, 0.0, 0.0, 1.0);
    glVertex3f(szy + szx * level, szy, 0.0);
    glVertex3f(0.0, szy, 0.0);
    glColor4f(0.0, 0.0, 0.0, 0.0);
    glVertex3f(0.0, 0.0, 0.0);
    glVertex3f(szx * level, 0.0, 0.0);
    glEnd;

    //-- draw +/- buttons ---
    bx := butWidth;
    by := butHeight;
    bo := butOffset;
    glBindTexture(GL_TEXTURE_2D, updwnTex);

    glBegin(GL_QUADS);
    glColor4f(1.0, 1.0, 1.0, 0.6);
    glTexCoord2f(1.0, 0.0); glVertex3f(bx - bo, by, 0.0);
    glTexCoord2f(0.0, 0.0); glVertex3f(0.0 - bo, by, 0.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(0.0 - bo, 0.0, 0.0);
    glTexCoord2f(1.0, 1.0); glVertex3f(bx - bo, 0.0, 0.0);
    glEnd;

    glColor4f(1.0, 1.0, 1.0, 0.5);
    glTranslatef(11.0, 0.0, 0.0);
    glScalef(sc, sc, 1.0);
    //game->ftFont->Render(buf);
    ftglRenderFont(uniGlobal.ftFont, PAnsiChar(buf));
  end;

  glPopMatrix;

  glPopMatrix;
end;

procedure MenuGL.drawTitle;
//var
//  tilt: PSingle;
begin
  //tilt := @titleTilt;
  //tilt^ := titleTilt;

  if ta0 < 90.0 then
    ta0 := ta0 + 0.7
  else
    if not thickText then
      ta0 := ta0 + 180.0
    else
      ta0 := ta0 + 5.0;

  if ta0 > 270.0 then ta0 := ta0 - 360.0;

  if ta1 < 90.0 then ta1 := ta1 + 0.55
  else
    if not thickText then
      ta1 := ta1 + 180.0
    else
      ta1 := ta1 + 8.0;

  if ta1 > 270.0 then ta1 := ta1 - 360.0;

  if thickText then
  begin
    Dec(tiltCount);
    if tiltCount = 0 then
      titleTilt := 360.0 + titleTilt
    else
      if tiltCount < 0 then
      begin
        titleTilt := titleTilt - 1.0;
        if titleTilt < -10.0 then
        begin
          tiltCount := 1500;
          titleTilt := -10.0;
        end;
      end
      else
        titleTilt := titleTilt - 0.01;
  end;

  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LEQUAL);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glColor4f(1.0, 1.0, 1.0, 1.0);
  glPushMatrix;
  glEnable(GL_TEXTURE_GEN_S);
  glEnable(GL_TEXTURE_GEN_T);
  glBindTexture(GL_TEXTURE_2D, envTex);
  glPushMatrix;
  glTranslatef(0.0, 1.0, 0.0);
  glRotatef(titleTilt, 1.0, 0.0, 0.0);
  glRotatef(ta0, 0.0, 1.0, 0.0);
  glCallList(listChrom);
  glPopMatrix;
  glPushMatrix;
  glTranslatef(0.0, -1.0, 0.0);
  glRotatef(titleTilt, 1.0, 0.0, 0.0);
  glRotatef(ta1, 0.0, 1.0, 0.0);
  glCallList(listBSU);
  glPopMatrix;
  glDisable(GL_TEXTURE_GEN_S);
  glDisable(GL_TEXTURE_GEN_T);
  glPopMatrix;
  glDisable(GL_DEPTH_TEST);
end;

procedure MenuGL.drawTitleBack;
var
  clr_c: array[0..3] of Single;
  clr_w: array[0..3] of Single;
  w, a, h, z, _as, _at: Single;
begin
  clr_c[0] := 1.0;
  clr_c[1] := 1.0;
  clr_c[2] := 1.0;
  clr_c[3] := 0.0;

  clr_w[0] := 1.0;
  clr_w[1] := 1.0;
  clr_w[2] := 1.0;
  clr_w[3] := 1.0;

  w := 9.0;
  a := 2.0;
  h := 1.4;
  z := 0.5;

  _as := a / (w + a);
  _at := a / (h + a);

  glBindTexture(GL_TEXTURE_2D, backTex);
  glMatrixMode(GL_TEXTURE);
  glPushMatrix;
  glTranslatef(amt * 0.1, amt * 0.5, 0.0);
  glRotatef(-amt * 100.0, 0.0, 1.0, 1.0);
  amt := amt - 0.01;
  //-- Top right
  glBegin(GL_TRIANGLE_STRIP);
  glTexCoord2f(1.0, 1.0 - _at); glColor4fv(@clr_c); glVertex3f(w + a, h, 0.0);
  glTexCoord2f(1.0, 1.0); glColor4fv(@clr_c); glVertex3f(w + a, h + a, 0.0);
  glTexCoord2f(1.0 - _as, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(w, h, 0.0);
  glTexCoord2f(1.0 - _as, 1.0); glColor4fv(@clr_c); glVertex3f(w, h + a, 0.0);
  glTexCoord2f(0.0, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(0.0, h, 0.0);
  glTexCoord2f(0.0, 1.0); glColor4fv(@clr_c); glVertex3f(0.0, h + a, 0.0);
  glEnd;
  glBegin(GL_TRIANGLE_STRIP);
  glTexCoord2f(1.0, 0.0); glColor4fv(@clr_c); glVertex3f(w + a, 0.0, z);
  glTexCoord2f(1.0, 1.0 - _at); glColor4fv(@clr_c); glVertex3f(w + a, h, 0.0);
  glTexCoord2f(1.0 - _as, 0.0); glColor4fv(@clr_w); glVertex3f(w, 0.0, z);
  glTexCoord2f(1.0 - _as, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(w, h, 0.0);
  glTexCoord2f(0.0, 0.0); glColor4fv(@clr_w); glVertex3f(0.0, 0.0, z);
  glTexCoord2f(0.0, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(0.0, h, 0.0);
  glEnd;
  //-- Top left
  glBegin(GL_TRIANGLE_STRIP);
  glTexCoord2f(0.0, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(0.0, h, 0.0);
  glTexCoord2f(0.0, 1.0); glColor4fv(@clr_c); glVertex3f(0.0, h + a, 0.0);
  glTexCoord2f(1.0 - _as, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(-w, h, 0.0);
  glTexCoord2f(1.0 - _as, 1.0); glColor4fv(@clr_c); glVertex3f(-w, h + a, 0.0);
  glTexCoord2f(1.0, 1.0 - _at); glColor4fv(@clr_c); glVertex3f(-w - a, h, 0.0);
  glTexCoord2f(1.0, 1.0); glColor4fv(@clr_c); glVertex3f(-w - a, h + a, 0.0);
  glEnd;
  glBegin(GL_TRIANGLE_STRIP);
  glTexCoord2f(0.0, 0.0); glColor4fv(@clr_w); glVertex3f(0.0, 0.0, z);
  glTexCoord2f(0.0, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(0.0, h, 0.0);
  glTexCoord2f(1.0 - _as, 0.0); glColor4fv(@clr_w); glVertex3f(-w, 0.0, z);
  glTexCoord2f(1.0 - _as, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(-w, h, 0.0);
  glTexCoord2f(1.0, 0.0); glColor4fv(@clr_c); glVertex3f(-w - a, 0.0, z);
  glTexCoord2f(1.0, 1.0 - _at); glColor4fv(@clr_c); glVertex3f(-w - a, h, 0.0);
  glEnd;
  //-- bottom right
  glBegin(GL_TRIANGLE_STRIP);
  glTexCoord2f(1.0, 1.0 - _at); glColor4fv(@clr_c); glVertex3f(w + a, -h, 0.0);
  glTexCoord2f(1.0, 0.0); glColor4fv(@clr_c); glVertex3f(w + a, 0.0, z);
  glTexCoord2f(1.0 - _as, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(w, -h, 0.0);
  glTexCoord2f(1.0 - _as, 0.0); glColor4fv(@clr_w); glVertex3f(w, 0.0, z);
  glTexCoord2f(0.0, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(0.0, -h, 0.0);
  glTexCoord2f(0.0, 0.0); glColor4fv(@clr_w); glVertex3f(0.0, 0.0, z);
  glEnd;
  glBegin(GL_TRIANGLE_STRIP);
  glTexCoord2f(1.0, 1.0); glColor4fv(@clr_c); glVertex3f(w + a, -h - a, 0.0);
  glTexCoord2f(1.0, 1.0 - _at); glColor4fv(@clr_c); glVertex3f(w + a, -h, 0.0);
  glTexCoord2f(1.0 - _as, 1.0); glColor4fv(@clr_c); glVertex3f(w, -h - a, 0.0);
  glTexCoord2f(1.0 - _as, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(w, -h, 0.0);
  glTexCoord2f(0.0, 1.0); glColor4fv(@clr_c); glVertex3f(0.0, -h - a, 0.0);
  glTexCoord2f(0.0, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(0.0, -h, 0.0);
  glEnd;
  //bottom left
  glBegin(GL_TRIANGLE_STRIP);
  glTexCoord2f(0.0, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(0.0, -h, 0.0);
  glTexCoord2f(0.0, 0.0); glColor4fv(@clr_w); glVertex3f(0.0, 0.0, z);
  glTexCoord2f(1.0 - _as, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(-w, -h, 0.0);
  glTexCoord2f(1.0 - _as, 0.0); glColor4fv(@clr_w); glVertex3f(-w, 0.0, z);
  glTexCoord2f(1.0, 1.0 - _at); glColor4fv(@clr_c); glVertex3f(-w - a, -h, 0.0);
  glTexCoord2f(1.0, 0.0); glColor4fv(@clr_c); glVertex3f(-w - a, 0.0, z);
  glEnd;
  glBegin(GL_TRIANGLE_STRIP);
  glTexCoord2f(0.0, 1.0); glColor4fv(@clr_c); glVertex3f(0.0, -h - a, 0.0);
  glTexCoord2f(0.0, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(0.0, -h, 0.0);
  glTexCoord2f(1.0 - _as, 1.0); glColor4fv(@clr_c); glVertex3f(-w, -h - a, 0.0);
  glTexCoord2f(1.0 - _as, 1.0 - _at); glColor4fv(@clr_w); glVertex3f(-w, -h, 0.0);
  glTexCoord2f(1.0, 1.0); glColor4fv(@clr_c); glVertex3f(-w - a, -h - a, 0.0);
  glTexCoord2f(1.0, 1.0 - _at); glColor4fv(@clr_c); glVertex3f(-w - a, -h, 0.0);
  glEnd;
  glPopMatrix;
  glMatrixMode(GL_MODELVIEW);

end;

procedure MenuGL.incItem;
var
  _config: Config;
  _hiScore: HiScore;
  game: Global;
  pos: array[0..2] of Single;
begin
  _config := uniConfig.instance;
  _hiScore := uniHiScore.getInstance;
  game := uniGlobal.getInstance;
  pos[0] := 0.0;
  pos[1] := 0.0;
  pos[2] := 25.0;

  case curSel of
    NewGame:
      begin
        activateItem;
      end;
    SkillLevel:
      begin
        _config.setGameSkillBase(_config.gameSkillBase + 0.1);
        _hiScore.print(_config.intSkill);
        game.newGame;
      end;
    GameLevel:
      begin
        Inc(uniGlobal.gameLevel);
        if uniGlobal.gameLevel > _config.maxLevel then
        begin
          mssgHelpOverride := True;
          mssgAlpha := 1.1;
          mssgText := '---- you must complete level ' + IntToStr(_config.maxLevel) + ' before you can select level ' + IntToStr(uniGlobal.gameLevel) + ' ----';
          uniGlobal.gameLevel := _config.maxLevel;
        end
        else
        begin
          game.newGame;
        end;
      end;
    Graphics:
      begin
        _config.setGfxLevel(_config.gfxLevel + 1);
      end;
    ScreenSize:
      begin
        _config.setScreenSize(_config.screenSize + 1);
        game.deleteTextures;
        toolkit.setVideoMode;
        game.loadTextures;
      end;
    FullScreen:
      begin
        if _config.fullScreen then
        begin
          _config.setFullScreen(True);
          game.deleteTextures;
          toolkit.setVideoMode;
          game.loadTextures;
        end;
      end;
    Sound:
      begin
        _config.setVolSound(_config.volSound + 0.05);
        _audio.setSoundVolume(_config.volSound);
        _audio.playSound(uniAudio.Explosion, pos);
      end;
    Music:
      begin
        _config.setVolMusic(_config.volMusic + 0.05);
        _audio.setMusicVolume(_config.volMusic);
      end;
    MouseSpeed:
      begin
        _config.setMouseSpeed(_config.mouseSpeed + 0.005);
      end;
    Quit:
      begin
        activateItem;
      end;
    NumSelections:
      begin

      end;
  end;
end;

procedure MenuGL.keyhit(_key: key);
begin
  case _key of
    KeyUp:
      begin
        if curSel = MenuSelection(0) then
        begin
          curSel := MenuSelection(Integer(NumSelections) - 1);
        end
        else
        begin
          curSel := MenuSelection(Integer(curSel) - 1);
        end;
        elecOffX := 0.0;
      end;
    KeyDown:
      begin
        curSel := MenuSelection((Integer(curSel) + 1) mod Integer(NumSelections));
        elecOffX := 0.0;
      end;
    KeyLeft: decItem;
    KeyRight: IncItem;
    KeyEnter: activateItem;
  end;
end;

procedure MenuGL.loadTextures;
begin
  LoadTexture('png/electric.png', elecTex);
  LoadTexture('png/menu_back.png', backTex);
  LoadTexture('png/heroAmmoFlash00.png', csrTex);
  LoadTexture('png/menu_updown.png', updwnTex);
  //-- Environment map
  glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);

  LoadTexture('png/reflect.png', envTex);

  listChrom := glGenLists(1);
  listBSU := glGenLists(1);
  thickText := True;
  createLists(thickText);
end;

procedure MenuGL.mousePress(but: Button; xi, yi: Integer);
var
  x, y, p, s, l, hw: Single;
  _config: Config;
  mSel: Integer;
begin
  if but = uniMainToolkit.Left then
  begin
    _config := uniConfig.instance;
    x := -2.0 * (0.5 - (xi / _config.screenW)) * 16.60;
    y := 2.0 * (0.5 - (yi / _config.screenH)) * 12.45;

    p := -y + (1.0 + txtHeight * 1.5);
    s := txtHeight * 2.5;
    mSel := -1;
    if p > 0.0 then
    begin
      // reset electric
      elecOffX := 0.0;
      p := p / s;
      mSel := floor(p);
      if (mSel >= 0) and (mSel < Integer(NumSelections)) then
      begin
        if mSel <> Integer(curSel) then
        begin
          curSel := MenuSelection(mSel);
          elecOffX := 0.0;
          mSel := -1;
        end;
      end;
    end;
    l := -8.0 - butOffset;
    hw := butWidth * 0.5;
    if mSel >= 0 then
    begin
      if (x > l) and (x < l + hw) then
        decItem()
      else
        if (x > l + hw) and (x < l + butWidth) then
          incItem()
        else
          activateItem()
    end;
  end;
end;

procedure MenuGL.startMenu;
begin
  elecOffX := 0.0;
  textAngle := 90.0;
  textCount := 500;
  thickText := True;
  createLists(thickText);
  uniGlobal.cursorPos[0] := 0.0;
  uniGlobal.cursorPos[1] := 0.0;
end;

end.

